#define _XOPEN_SOURCE 500
 
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

char *makemsg(char f[])
{
  char		       *msg;
  size_t		s_file;
  s_file = strlen(f);
  msg = malloc(s_file + 9);
  strncpy(msg,"mysplit: ",9);
  strncat(msg,f,s_file);
  return msg;
}

char *produce_next_name(char *pref)
{
  static char          *name = NULL;
  static char           c1 = 'a', c2 = 'a';
  static int            pos;
  if (!name)
    {
      name = malloc(strlen(pref) + 4);
      pos = strlen(pref) + 1;
      strncpy(name, pref, strlen(pref));
      name[pos-1] = '.';
    }
  name[pos] = c1;
  name[pos+1] = c2++;
  if (c2 > 'z')
    {
      ++c1; //handle no more than 26*26 blocks
      c2 = 'a';
    }
  return name;
}

void filesplit (char f[], int step, char res[])
{
	int 			fd, fd2;
  char			buf[step];
  int				r;
  char 			*nextname;

	if((fd = open(f,O_RDONLY)) == -1)
    {
    	perror (makemsg(f));
			exit (2);
    }

	while((r = read(fd, buf, step)))
	{
		if(r == -1)
  	{
  		if ( errno == EINTR || errno == EAGAIN )
		    continue;
			perror (makemsg(f));
		  exit (3);
		}
		
		nextname = produce_next_name(res);
		if((fd2 = open (nextname, O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1)
		{
			perror (makemsg(f));
			exit (4);
		}
		
		while (write(fd2,buf,r) == -1)
		{
			if ( errno == EINTR || errno == EAGAIN )
		    continue;
			perror (makemsg(nextname));
		  exit (5);
		}
		close(fd2);
	}
	close (fd);
}

int main(int argc, char *argv[])
{
  if(argc == 2 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
  {
    write(STDOUT_FILENO,"Usage : ",8);
   	write(STDOUT_FILENO, argv[0],strlen(argv[0]));
   	write(STDOUT_FILENO," file subfile_size subfile_name (26*26 subfiles max)",52);
    return (0);
  }
  
	if(argc < 4)
  {
    write(STDERR_FILENO,"Missing parameters\nUsage : ",28);
   	write(STDERR_FILENO, argv[0],strlen(argv[0]));
   	write(STDERR_FILENO," file subfile_size subfile_name (26*26 subfiles max)",52);
    exit(1);
  }
  
  filesplit (argv[1], atoi(argv[2]), argv[3]);
	return (!argc);
}
